package com.doctcloud.common.shardingsphere.strategy;

import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * 按日期分表算法（实现 ShardingSphere 标准分片算法接口）
 * 表名格式：t_order_202401（yyyyMM 后缀）
 */
public class DateShardingStrategy implements StandardShardingAlgorithm<LocalDate> {
    // 日期格式化器（表名后缀：yyyyMM）
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMM");

    /**
     * 精确分片（处理 = 条件，如 create_time = '2024-01-15'）
     */
    @Override
    public String doSharding(Collection<String> availableTableNames, PreciseShardingValue<LocalDate> shardingValue) {
        // 1. 获取分片键值（如 2024-01-15）
        LocalDate shardingDate = shardingValue.getValue();
        // 2. 格式化为表名后缀（如 202401）
        String tableSuffix = FORMATTER.format(shardingDate);
        // 3. 匹配可用表名（如 t_order_202401）
        for (String tableName : availableTableNames) {
            if (tableName.endsWith(tableSuffix)) {
                return tableName;
            }
        }
        // 无匹配表时抛出异常
        throw new IllegalArgumentException(
                String.format("未找到匹配的分表，可用表：%s，分片值：%s", availableTableNames, shardingValue)
        );
    }

    /**
     * 范围分片（处理 >、<、BETWEEN 条件，如 create_time BETWEEN '2024-01-01' AND '2024-03-31'）
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTableNames, RangeShardingValue<LocalDate> shardingValue) {
        // 1. 获取范围条件（如 开始日期 2024-01-01，结束日期 2024-03-31）
        LocalDate startDate = shardingValue.getValueRange().lowerEndpoint();
        LocalDate endDate = shardingValue.getValueRange().upperEndpoint();

        // 2. 遍历可用表名，匹配范围內的表（如 t_order_202401、t_order_202402、t_order_202403）
        return availableTableNames.stream()
                .filter(tableName -> isTableInDateRange(tableName, startDate, endDate))
                .collect(Collectors.toList());
    }

    /**
     * 辅助方法：判断表名是否在日期范围内
     */
    private boolean isTableInDateRange(String tableName, LocalDate startDate, LocalDate endDate) {
        try {
            // 提取表名后缀（如从 t_order_202401 提取 202401）
            String suffix = tableName.substring(tableName.lastIndexOf("_") + 1);
            // 解析为 LocalDate（取当月第一天，如 202401 → 2024-01-01）
            LocalDate tableDate = LocalDate.parse(suffix + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
            // 判断表日期是否在 [startDate, endDate] 范围内
            return !tableDate.isBefore(startDate) && !tableDate.isAfter(endDate);
        } catch (Exception e) {
            // 表名格式异常时，视为不在范围内
            return false;
        }
    }

    /**
     * 初始化方法（可读取配置参数，如自定义日期格式）
     */
    @Override
    public void init(Properties props) {
        // 如需从配置文件读取参数（如格式、分表粒度），可在此处理
        // 示例：String format = props.getProperty("date-format", "yyyyMM");
    }

    @Override
    public String getType() {
        // 返回算法类型标识（自定义，与配置文件中的 algorithm-type 对应）
        return "DATE_STANDARD";
    }

    @Override
    public Collection<String> getTypeAliases() {
        return StandardShardingAlgorithm.super.getTypeAliases();
    }

    @Override
    public Properties getProps() {
        return null;
    }
}